home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 25 / Cream of the Crop 25.iso / program / fpk65_66.zip / SOURCE / RTL / DOS / SYSTEM.INC < prev    next >
Text File  |  1997-02-11  |  45KB  |  1,676 lines

  1. {****************************************************************************
  2.  
  3.                        Copyright (c) 1993,1997 by
  4.                     Florian Klaempfl & Michael Spiegel
  5.  
  6.  ****************************************************************************}
  7.  
  8.  
  9. { betriebssystemunabhaengige Implementationen der Unit System }
  10.  
  11.     {$I SET.INC}
  12.  
  13.     type       
  14.        textbuf = array[0..127] of char;
  15.  
  16.        textrec = record
  17.           handle : word;
  18.           mode : word;
  19.           bufsize : word;
  20.           { private : word; PRIVATE is a key word }
  21.           _private : word;
  22.           bufpos : word;
  23.           bufend : word;
  24.           bufptr : ^textbuf;
  25.           openfunc : pointer;
  26.           inoutfunc : pointer;
  27.           flushfunc : pointer;
  28.           closefunc : pointer;
  29.           userdata : array[1..16] of byte;
  30. {$ifdef linux}
  31.           name : string[255];
  32. {$else}
  33.           name : string[79];
  34. {$endif}
  35.           buffer : textbuf;
  36.        end;
  37.  
  38.     { folgende Routinen nicht direkt aufrufen }
  39.  
  40.     procedure help_constructor;
  41.  
  42.       begin
  43.          asm
  44. .globl HELP_CONSTRUCTOR_NE
  45. HELP_CONSTRUCTOR_NE:
  46.             { Einsprung ohne Prolog, da wir ESP vom Constructor brauchen }
  47.             { Stack (relativ zu %ebp):
  48.                 12 Self
  49.                 8 VMT-Adresse
  50.                 4 Hauptprogramm-Addr
  51.                 0 %ebp
  52.             }
  53.             { Self initialisieren? }
  54.             orl %esi,%esi
  55.             jne LHC_4
  56.             { Speicher anfordern, aber erst Register retten }
  57.             { Hilfsvariable }
  58.             subl $4,%esp
  59.             movl %esp,%esi
  60.             { Register retten }
  61.             pushal
  62.             { Speichergröße }
  63.             movl 8(%ebp),%eax
  64.             pushl (%eax)
  65.             pushl %esi
  66.             call GETMEM
  67.             popal
  68.             { Speicherbereich nach %esi }
  69.             movl (%esi),%esi
  70.             addl $4,%esp
  71.             { falls kein Speicher vorhanden fail() }
  72.             orl %esi,%esi
  73.             jz LHC_5
  74.             { Self für Konstruktor initialisieren }
  75.             movl %esi,12(%ebp)
  76.          LHC_4:
  77.             { VMT-Adresse in Instanz eintragen... }
  78.             movl 8(%ebp),%eax
  79.             { ...falls eine übergeben wurde }
  80.             orl %eax,%eax
  81.             jnz LHC_7
  82.             { falls der Konstruktor nichts macht, darf das Zero-Flag }
  83.             { nicht gesetzt sein, da sonst fail() "aufgerufen" wird }
  84.             incl %eax
  85.             ret
  86.          LHC_7:
  87.             movl %eax,(%esi)
  88.          LHC_5:
  89.             ret
  90.          end;
  91.       end;
  92.  
  93.     procedure help_fail;
  94.  
  95.       begin
  96.          asm
  97.          end;
  98.       end;
  99.  
  100.     procedure help_destructor;
  101.  
  102.       begin
  103.          asm
  104.             { Stack (relativ zu %ebp):
  105.                 12 Self
  106.                 8 VMT-Adresse
  107.                 4 Hauptprogramm-Addr
  108.                 0 %ebp
  109.             }
  110. .globl HELP_DESTRUCTOR_NE
  111. HELP_DESTRUCTOR_NE:
  112.             { temporäre Variable }
  113.             subl $4,%esp
  114.             movl %esp,%edi
  115.             pushal
  116.             { muß das Objekt gelöscht werden ? }
  117.             movl 8(%ebp),%eax
  118.             orl %eax,%eax
  119.             jz LHD_3
  120.             { ja, dann Größe aus SELF! laden }
  121.             movl 12(%ebp),%eax
  122.             { VMT-Zeiger (aus Self) nach %ebx }
  123.             movl (%eax),%ebx
  124.             { und Größe auf den Stack }
  125.             pushl (%ebx)
  126.             { SELF }
  127.             movl %eax,(%edi)
  128.             pushl %edi
  129.             call FREEMEM
  130.          LHD_3:
  131.             popal
  132.             addl $4,%esp
  133.             ret
  134.          end;
  135.       end;
  136.  
  137.     procedure runerror(w : word);
  138.  
  139.       function get_addr : longint;
  140.       
  141.         begin
  142.            asm
  143.               movl 16(%ebp),%eax
  144.            end ['EAX'];
  145.         end;
  146.  
  147.       begin
  148.          writeln('Laufzeitfehler ',w,' bei ',get_addr);
  149.          halt(1);
  150.       end;
  151.  
  152.     procedure io1(addr : longint);[public,alias: 'IOCHECK'];
  153.     
  154.       var
  155.          l : longint;
  156.  
  157.       begin
  158.          { da IOCHECK direkt aufgerufen wird und später der Optimierer }
  159.          { vielleicht auch global Register zuweist               }
  160.          asm
  161.             pushal
  162.          end;
  163.          l:=ioresult;
  164.          if l<>0 then
  165.            begin
  166.               writeln('IO-Error ',l,' at ',addr);
  167.               halt(1);
  168.            end;
  169.          asm
  170.             popal
  171.          end;
  172.       end;
  173.  
  174.     procedure re_overflow;[public,alias: 'RE_OVERFLOW'];
  175.  
  176.       var
  177.          addr : longint;
  178.  
  179.       begin
  180.          { Überlauf war kurz vor der Returnadresse }
  181.          asm
  182.             movl 4(%ebp),%edi
  183.             movl %edi,-4(%ebp)
  184.          end;
  185.          writeln('Überlauf bei ',addr);
  186.          halt(1);
  187.       end;
  188.  
  189. {$E-}
  190.  
  191.     { kopiert Strings }
  192.     { Darf nie direkt aufgerufen werden, da  *** nicht ***  mit }
  193.     { einer Exceptionadresse auf dem Stack gerechnet wird }
  194.     { außerdem werden Parameter von links nach rechts erwartet!! }
  195.     procedure strcopy(dstr,sstr : pointer;len : longint);[public,alias: 'STRCOPY'];
  196.     
  197.       begin
  198.          asm
  199.             cld
  200.             movl 16(%ebp),%edi    // Parameter laden
  201.             movl 12(%ebp),%esi
  202.             movl 8(%ebp),%ecx
  203.             lodsb        // Laenge von Quelle laden
  204.             cmpb %cl,%al
  205.             jbe LM4
  206.             movb %cl,%al    // wenn laenger als max. Laenge des Ziel,
  207.                         // dann Quelle abschneiden
  208.          LM4:
  209.             movzbl %al,%eax
  210.             mov %eax,%ecx
  211.             stosb        // Länge speichern
  212.             shrl $2,%ecx     // Erst dwordweise kopieren
  213.             rep
  214.             movsl
  215.             movl %eax,%ecx     // ...und nun die restlichen Bytes
  216.             andl $3,%ecx
  217.             rep
  218.             movsb
  219.             leave        // eigenes Return, wegen anderem Stackframe
  220.             ret $12
  221.          end;
  222.       end;
  223. {$E-}
  224.     { verknüpft Strings }
  225.     { Darf nie direkt aufgerufen werden, da  *** nicht ***  mit }
  226.     { einer Exceptionadresse auf dem Stack gerechnet wird }
  227.     { haengt s2 an s1 an }
  228.     { außerdem werden Parameter von links nach rechts erwartet!! }
  229.     procedure strconcat(s1,s2 : pointer);[public,alias: 'STRCONCAT'];
  230.  
  231.       begin
  232.          asm
  233.         movl 12(%ebp),%edi    // Laenge des ersten Strings nach ECX
  234.         movb (%edi),%cl
  235.         movzbl %cl,%ecx
  236.         movl 12(%ebp),%edi  // Startadresse fuer den zweiten String
  237.                     // berechnen
  238.         lea 1(%edi,%ecx),%edi
  239.         negl %ecx        // Restplatz berechnen
  240.         addl $0xff,%ecx
  241.         movl 8(%ebp),%esi    // Laenge des zweiten Strings nach AL
  242.         lodsb
  243.             cmpb %cl,%al
  244.             jbe LM5
  245.             movb %cl,%al    // falls zu lang, dann abschneiden
  246.      LM5:
  247.         movb %al,%cl
  248.         movl 12(%ebp),%ebx
  249.         addb %cl,(%ebx)     // Resultatlaenge schreiben
  250.         movzbl %cl,%ecx
  251.             movl %ecx,%eax     // Laenge retten
  252.             shrl $2,%ecx     // Erst dwordweise kopieren
  253.             cld
  254.             rep
  255.             movsl
  256.             movl %eax,%ecx     // ...und nun die restlichen Bytes
  257.             andl $3,%ecx
  258.             rep
  259.             movsb
  260.             leave        // eigenes Return, wegen anderem Stackframe
  261.             ret $8
  262.          end ['EAX','EBX','ECX','EDI'];
  263.       end;
  264.  
  265.     { vergleicht Strings (Flags sind danach gesetzt }
  266.     { Darf nie direkt aufgerufen werden, da  *** nicht ***  mit }
  267.     { einer Exceptionadresse auf dem Stack gerechnet wird }
  268.     { außerdem werden Parameter von links nach rechts erwartet!! }
  269. {$E-}
  270.     procedure strcmp(dstr,sstr : pointer);[public,alias: 'STRCMP'];
  271.     
  272.       begin
  273.          asm
  274.             movl 12(%ebp),%esi
  275.             movl 8(%ebp),%edi
  276.             cld
  277.             lodsb        // Laenge des ersten Strings nach AL
  278.             movb (%edi),%ah    // Laenge des zweiten Strings nach AH
  279.             incl %edi
  280.             movb %al,%cl    // den kuerzeren String berechnen
  281.             cmpb %ah,%cl
  282.             jbe LSTRCONCAT1
  283.             movb %ah,%cl
  284.         LSTRCONCAT1:
  285.             orb %cl,%cl        // Laenge gleich 0 ?
  286.             jz LSTRCONCAT2
  287.             movzbl %cl,%ecx
  288.             rep            // Stringvergleich
  289.             cmpsb
  290.             jne LSTRCONCAT3    // Ende erreicht ?
  291.         LSTRCONCAT2:
  292.             cmpb %ah,%al    // dann Laengenvergleich
  293.         LSTRCONCAT3:
  294.             leave        // eigenes Return, wegen anderem Stackframe
  295.             ret $8
  296.          end;
  297.       end;
  298.  
  299.     function strpas(p : pchar) : string;
  300.  
  301.       begin
  302.          asm
  303.             cld
  304.             movl 12(%ebp),%edi
  305.             movl %edi,%esi               // Quelle
  306.             movl $0xffffffff,%ecx        // nach Ende suchen
  307.             xorb %al,%al
  308.             repne
  309.             scasb
  310.             notl %ecx
  311.             decl %ecx
  312.             movl 8(%ebp),%edi          //  Ziel neu laden
  313.             movb %cl,%al
  314.             stosb
  315.             rep
  316.             movsb
  317.          end ['ECX','EAX','ESI','EDI'];
  318.       end;
  319.  
  320.     function strlen(p : pchar) : longint;
  321.  
  322.       begin
  323.          asm
  324.             cld
  325.             movl 8(%ebp),%edi
  326.             movl $0xffffffff,%ecx
  327.             xorb %al,%al
  328.             repne
  329.             scasb
  330.             movl $0xfffffffe,%eax
  331.             subl %ecx,%eax
  332.             leave
  333.             ret $4
  334.          end ['EDI','ECX','EAX'];
  335.       end;
  336.  
  337.     procedure move(var source;var dest;count : longint);
  338.  
  339.       { count : EBP+16 }
  340.  
  341.       var
  342.          sp,dp : pointer;
  343.  
  344.       { sp : EBP-4 }
  345.       { dp : EBP-8 }
  346.  
  347.       begin
  348.          if count=0 then
  349.            exit;
  350.          sp:=@source;
  351.          dp:=@dest;
  352.          if sp>dp then
  353.            asm
  354.               cld
  355.               movl 16(%ebp),%ecx
  356.               movl -4(%ebp),%esi
  357.               movl -8(%ebp),%edi
  358.               movl %ecx,%eax
  359.               shrl $2,%ecx
  360.               rep
  361.               movsl
  362.               movl %eax,%ecx
  363.               andl $3,%ecx
  364.               rep
  365.               movsb
  366.            end ['ESI','EDI','ECX','EAX']
  367.          else if sp<dp then
  368.            { vorsichtshalber rückwärts kopieren: }
  369.            asm
  370.               std
  371.               movl 16(%ebp),%ecx
  372.               movl -4(%ebp),%esi
  373.               movl -8(%ebp),%edi
  374.               addl %ecx,%esi
  375.               addl %ecx,%edi
  376.               movl %ecx,%eax
  377.               andl $3,%ecx
  378.               orl %ecx,%ecx
  379.               jz LMOVE1
  380.               { ESI und EDI müssen erst richtig berechnet werden }
  381.               decl %esi
  382.               decl %edi
  383.               rep
  384.               movsb
  385.               incl %esi
  386.               incl %edi
  387.            LMOVE1:
  388.               subl $4,%esi
  389.               subl $4,%edi
  390.               movl %eax,%ecx
  391.               shrl $2,%ecx
  392.               rep
  393.               movsl
  394.               cld
  395.            end ['ESI','EDI','ECX'];
  396.       end;
  397.  
  398.     procedure fillchar(var x;count : longint;value : byte);
  399.  
  400.       begin
  401.          asm
  402.             movl 8(%ebp),%edi
  403.             movl 12(%ebp),%ecx
  404.             movb 16(%ebp),%dl
  405.             // EAX mit 4fachem Byte füllen:
  406.             movb %dl,%dh
  407.             movw %dx,%ax
  408.             shll $16,%eax
  409.             movw %dx,%ax
  410.             movl %ecx,%edx
  411.             shrl $2,%ecx
  412.             cld
  413.             rep
  414.             stosl
  415.             movl %edx,%ecx
  416.             andl $3,%ecx
  417.             rep
  418.             stosb
  419.          end ['EAX','ECX','EDX','EDI'];
  420.       end;
  421.  
  422.     procedure fillchar(var x;count : longint;value : char);
  423.  
  424.       begin
  425.          fillchar(x,count,byte(value));
  426.       end;
  427.  
  428.     procedure fillword(var x;count : longint;value : word);
  429.  
  430.       begin
  431.          asm
  432.             movl 8(%ebp),%edi
  433.             movl 12(%ebp),%ecx
  434.             movw 16(%ebp),%dx
  435.             // EAX mit 4fachem Byte füllen:
  436.             movw %dx,%ax
  437.             shll $16,%eax
  438.             movw %dx,%ax
  439.             movl %ecx,%edx
  440.             shrl $1,%ecx
  441.             cld
  442.             rep
  443.             stosl
  444.             movl %edx,%ecx
  445.             andl $1,%ecx
  446.             rep
  447.             stosw
  448.          end ['EAX','ECX','EDX','EDI'];
  449.       end;
  450.  
  451.     {$I INNR.INC}
  452.  
  453.     function lo(w : word) : byte;[INTERNPROC: in_lo_word];
  454.     function hi(w : word) : byte;[INTERNPROC: in_hi_word];
  455.     function lo(i : integer) : byte;[INTERNPROC: in_lo_word];
  456.     function hi(i : integer) : byte;[INTERNPROC: in_hi_word];
  457.  
  458.     function lo(l : longint) : word;[INTERNPROC: in_lo_long];
  459.     function hi(l : longint) : word;[INTERNPROC: in_hi_long];
  460.  
  461.     function ord(c : char) : byte;[INTERNPROC: in_ord_char];
  462.  
  463.     {!!!!!! nicht besonders schnell, aber einfach }
  464.     function ord(b : boolean) : byte;
  465.     
  466.       begin
  467.          asm
  468.             movb 8(%ebp),%al
  469.             leave
  470.             ret
  471.          end;
  472.       end;
  473.       
  474.     function chr(b : byte) : char;[INTERNPROC: in_chr_byte];
  475.  
  476.     function length(s : string) : byte;[INTERNPROC: in_length_string];
  477.  
  478.     procedure inc(var i : longint);[INTERNPROC: in_inc_dword];
  479.     procedure inc(var i : integer);[INTERNPROC: in_inc_word];
  480.     procedure inc(var i : word);[INTERNPROC: in_inc_word];
  481.     procedure inc(var i : shortint);[INTERNPROC: in_inc_byte];
  482.     procedure inc(var i : byte);[INTERNPROC: in_inc_byte];
  483.     procedure dec(var i : longint);[INTERNPROC: in_dec_dword];
  484.     procedure dec(var i : integer);[INTERNPROC: in_dec_word];
  485.     procedure dec(var i : word);[INTERNPROC: in_dec_word];
  486.     procedure dec(var i : shortint);[INTERNPROC: in_dec_byte];
  487.     procedure dec(var i : byte);[INTERNPROC: in_dec_byte];
  488.  
  489.     procedure inc(var i : longint;a : longint);
  490.  
  491.       begin
  492.          i:=i+a;
  493.       end;
  494.  
  495.     procedure dec(var i : longint;a : longint);
  496.  
  497.       begin
  498.          i:=i-a;
  499.       end;
  500.  
  501.     procedure dec(var i : word;a : longint);
  502.  
  503.       begin
  504.          i:=i-a;
  505.       end;
  506.  
  507.     procedure inc(var i : word;a : longint);
  508.  
  509.       begin
  510.          i:=i+a;
  511.       end;
  512.  
  513.     procedure dec(var i : integer;a : longint);
  514.  
  515.       begin
  516.          i:=i-a;
  517.       end;
  518.  
  519.     procedure inc(var i : integer;a : longint);
  520.  
  521.       begin
  522.          i:=i+a;
  523.       end;
  524.  
  525.     procedure dec(var i : byte;a : longint);
  526.  
  527.       begin
  528.          i:=i-a;
  529.       end;
  530.  
  531.     procedure inc(var i : byte;a : longint);
  532.  
  533.       begin
  534.          i:=i+a;
  535.       end;
  536.  
  537.     procedure dec(var i : shortint;a : longint);
  538.  
  539.       begin
  540.          i:=i-a;
  541.       end;
  542.  
  543.     procedure inc(var i : shortint;a : longint);
  544.  
  545.       begin
  546.          i:=i+a;
  547.       end;
  548.  
  549.     function abs(l : longint) : longint;
  550.  
  551.       begin
  552.          asm
  553.             movl 8(%ebp),%eax
  554.             orl %eax,%eax
  555.             jns LMABS1
  556.             negl %eax
  557.          LMABS1:
  558.             leave
  559.             ret $4
  560.          end ['EAX'];
  561.       end;
  562.  
  563.     function odd(l : longint) : boolean;
  564.  
  565.       begin
  566.         asm
  567.            movl 8(%ebp),%eax
  568.            andl $1,%eax
  569.            setnz %al
  570.            leave
  571.            ret $4
  572.         end ['EAX'];
  573.       end;
  574.  
  575.     function sqr(l : longint) : longint;
  576.  
  577.       begin
  578.          asm
  579.             movl 8(%ebp),%eax
  580.             imull %eax,%eax
  581.             leave
  582.             ret $4
  583.          end ['EAX'];
  584.       end;
  585.  
  586.     {$I MATH.INC}
  587.  
  588.     procedure str(l : longint;var s : string);
  589.  
  590.       var
  591.          buffer : array[0..11] of byte;
  592.  
  593.       begin
  594.          { Workaround: }
  595.          if l=$80000000 then
  596.            begin
  597.               s:='-2147483648';
  598.               exit;
  599.            end;
  600.          asm
  601.             movl 8(%ebp),%eax        // Integer laden
  602.             movl 12(%ebp),%edi        // Stringadresse laden
  603.             xorl %ecx,%ecx        // Stringlaenge=0
  604.             xorl %ebx,%ebx        // Bufferlaenge=0
  605.             movl $0x0a,%esi        // 10 als Konstante zum Dividieren laden
  606.             testl $0x80000000,%eax    // vorzeichenbehaftet
  607.             jz LM2
  608.             neg %eax
  609.             movb $0x2d,1(%edi)      // '-' in String kopieren
  610.             incl %ecx
  611.          LM2:
  612.             cdq
  613.             idivl %esi,%eax
  614.             addb $0x30,%dl        // Rest in ASCII umrechnen
  615.             movb %dl,-12(%ebp,%ebx)
  616.             incl %ebx
  617.             cmpl $0,%eax
  618.             jnz LM2
  619.                             // String umkopieren
  620.          LM3:
  621.             movb -13(%ebp,%ebx),%al     // -13 da EBX erst spaeter
  622.                                 // dekremiert wird (spart Vergleich)
  623.             movb %al,1(%edi,%ecx)
  624.             incl %ecx
  625.             decl %ebx
  626.             jnz LM3
  627.             movb %cl,(%edi)        // Stringlaenge kopieren
  628.          end;
  629.       end;
  630.  
  631.    procedure str(i : integer;var s : string);
  632.  
  633.      begin
  634.         str(longint(i),s);
  635.      end;
  636.         
  637.    procedure str(si : shortint;var s : string);
  638.    
  639.      begin
  640.         str(longint(si),s);
  641.      end;
  642.      
  643.    procedure str(b : byte;var s : string);
  644.    
  645.      begin
  646.         str(longint(b),s);
  647.      end;
  648.      
  649.    procedure str(w : word;var s : string);
  650.    
  651.      begin
  652.         str(longint(w),s);
  653.      end;
  654.  
  655.    { weder besonders genau noch schnell, aber solide und leicht verständlich }
  656.  
  657.     procedure val(const s : string;var d : double;var code : word);
  658.  
  659.       var
  660.          { faster on a pentium }
  661.          esign,sign : double;
  662.  
  663.          i : longint;
  664.          exponent : longint;
  665.          flags : byte;
  666.          hd : double;
  667.  
  668.       begin
  669.          d:=0;
  670.          code:=1;
  671.          exponent:=0;
  672.          esign:=1;
  673.          flags:=0;
  674.          sign:=1;
  675.          while (s[code]=' ') or (s[code]=#9) do
  676.            inc(code);
  677.          if s[code]='+' then
  678.            inc(code)
  679.          else if s[code]='-' then
  680.            begin
  681.               sign:=-1.0;
  682.               inc(code);
  683.            end;
  684.          while (s[code]>='0') and (s[code]<='9') and (length(s)>=code) do
  685.            begin
  686.               { Vorkomma gelesen }
  687.               flags:=flags or 1;
  688.               d:=d*10;
  689.               d:=d+(ord(s[code])-ord('0'));
  690.               inc(code);
  691.            end;
  692.          { Kommastellen ? }
  693.          if (s[code]='.') and (length(s)>=code) then
  694.            begin
  695.               hd:=0.1;
  696.               inc(code);
  697.               { nach einem "Komma" muß eine Ziffer folgen }
  698.               if not((s[code]>='0') and (s[code]<='9')) or (length(s)<code) then
  699.                 begin
  700.                    d:=0.0;
  701.                    exit;
  702.                 end;
  703.               while (s[code]>='0') and (s[code]<='9') and (length(s)>=code) do
  704.                 begin
  705.                    { Nackkomma gelesen }
  706.                    flags:=flags or 2;
  707.                    d:=d+hd*(ord(s[code])-ord('0'));
  708.                    hd:=hd/10.0;
  709.                    inc(code);
  710.                 end;
  711.            end;
  712.          { weder Vorkomma- noch Nachkommastellen, dann abbrechen }
  713.          if flags=0 then
  714.            begin
  715.               d:=0.0;
  716.               exit;
  717.            end;
  718.          { Exponent ? }
  719.          if (upcase(s[code])='E') and (length(s)>=code) then
  720.            begin
  721.               inc(code);
  722.               if s[code]='+' then
  723.                 inc(code)
  724.               else if s[code]='-' then
  725.                 begin
  726.                    esign:=-1;
  727.                    inc(code);
  728.                 end;
  729.               if not((s[code]>='0') and (s[code]<='9')) or (length(s)<code) then
  730.                 begin
  731.                    d:=0.0;
  732.                    exit;
  733.                 end;
  734.               while (s[code]>='0') and (s[code]<='9') and (length(s)>=code) do
  735.                 begin
  736.                    exponent:=exponent*10;
  737.                    exponent:=exponent+ord(s[code])-ord('0');
  738.                    inc(code);
  739.                 end;
  740.            end;
  741.          { nun noch Exponent einrechnen }
  742.          if esign>0 then
  743.            for i:=1 to exponent do
  744.              d:=d*10
  745.          else
  746.            for i:=1 to exponent do
  747.              d:=d/10;
  748.          { nicht alle Zeichen gelesen ? }
  749.          if length(s)>=code then
  750.            begin
  751.               d:=0.0;
  752.               exit;
  753.            end;
  754.          { evalute sign }
  755.          d:=d*sign;
  756.          { success ! }
  757.          code:=0;
  758.       end;
  759.  
  760.     procedure val(const s : string;var b : byte);
  761.  
  762.       var
  763.          l : longint;
  764.  
  765.       begin
  766.          val(s,l);
  767.          b:=l;
  768.       end;
  769.  
  770.     procedure val(const s : string;var b : byte;var code : word);
  771.  
  772.       var
  773.          l : longint;
  774.  
  775.       begin
  776.          val(s,l,code);
  777.          b:=l;
  778.       end;
  779.  
  780.     procedure val(const s : string;var v : longint;var code : word);
  781.  
  782.       var
  783.          i : byte;
  784.          u : byte;
  785.          negativ : boolean;
  786.  
  787.       begin
  788.          negativ := false;
  789.          code := 1;
  790.          u := 0;
  791.          v := 0;
  792.          case s[1] of
  793.             '-' : begin
  794.                      negativ := true;
  795.                      code := 2;
  796.                   end;
  797.             '+' : code := 2;
  798.          end;
  799.          case s[code] of
  800.             '$' : begin
  801.                      i := 16;
  802.                      inc (code);
  803.                      while s[code] = #48 do inc (code);
  804.                      if ord (s[0]) - code > 7 then
  805.                         begin
  806.                            inc (code,8);
  807.                            exit;
  808.                         end;
  809.                   end;
  810.             '%' : begin
  811.                      i := 2;
  812.                      inc (code);
  813.                   end
  814.             else i := 10;
  815.          end;
  816.          u := 0;
  817.          v := 0;
  818.          while chr (code) <= s[0] do
  819.            begin
  820.               case s[code] of
  821.                  #48..#57  : u := ord (s[code]) - 48;
  822.                  #65..#70  : u := ord (s[code]) - 55;
  823.                  #97..#104 : u := ord (s[code]) - 87
  824.                  else u := 16;
  825.               end;
  826.               if (2147483647 - v*i < u) and ((i = 10) or (i = 2)) then u := 16;
  827.               if u >= i then
  828.                 begin
  829.                    v := 0;
  830.                    exit;
  831.                 end;
  832.                v := (v*i + u);
  833.                inc (code);
  834.             end;
  835.          code := 0;
  836.          if negativ then v := 0-v;
  837.       end;
  838.  
  839.     procedure val(const s : string;var v : longint);
  840.  
  841.      var
  842.         code : word;
  843.  
  844.      begin
  845.         val (s,v,code);
  846.      end;
  847.  
  848.     {$I real2str.inc}
  849.  
  850.     procedure str(d : double;var s : string);
  851.  
  852.       begin
  853.          str_real(-1,d,s);
  854.       end;
  855.       
  856.     var
  857.        randseed : longint;
  858.  
  859.     function random(l : longint) : longint;
  860.  
  861.       begin
  862.          randseed:=randseed*134775813+1;
  863.          random:=abs(randseed mod l);
  864.       end;
  865.  
  866.     { don't call this direct, the call is generated by the compiler }
  867.     procedure do_exit;[public,alias: '__EXIT'];
  868.  
  869.       begin
  870.          while exitproc<>nil do
  871.            begin
  872. {$ifdef DOS}
  873.               asm
  874.                  movl U_SYSTEM_EXITPROC,%eax
  875.                  call %eax
  876.               end;
  877. {$endif}
  878. {$ifdef OS2}
  879.               asm
  880.                  movl U_SYSOS2_EXITPROC,%eax
  881.                  call %eax
  882.               end;
  883. {$endif}
  884. {$ifdef LINUX}
  885.               asm
  886.                  movl U_SYSLINUX_EXITPROC,%eax
  887.                  call %eax
  888.               end;
  889. {$endif}
  890.            end;
  891.      end;
  892.  
  893. {****************************************************************************
  894.                     subroutines for file management
  895.  ****************************************************************************}
  896.         
  897.     type
  898.        filerec = record
  899.           handle : word;
  900.           mode : word;
  901.           recsize : word;
  902.           _private : array[1..26] of byte;
  903.           userdata : array[1..16] of byte;
  904.           name : string[79];
  905.        end;
  906.  
  907.     procedure doswrite(h,addr,len : longint);forward;
  908.     function dosread(h,addr,len : longint) : longint;forward;
  909.  
  910.     procedure fileinoutfunc(var f : textrec);
  911.  
  912.       begin
  913.          if f.mode=fmoutput then
  914.            begin
  915.               doswrite(f.handle,longint(f.bufptr),f.bufpos);
  916.            end
  917.          else if f.mode=fminput then
  918.            begin
  919.               f.bufend:=dosread(f.handle,longint(f.bufptr),f.bufsize);
  920.            end
  921.          else halt(100);
  922.          f.bufpos:=0;
  923.       end;
  924.  
  925.     type
  926.         dateifunc = procedure(var t : textrec);
  927.  
  928.     procedure fileopenfunc(var f : textrec);forward;
  929.  
  930.     procedure assign(var t : text;const s : string);
  931.  
  932.       begin
  933.          textrec(t).mode:=fmclosed;
  934.          textrec(t).bufsize:=128;
  935.          textrec(t).bufpos:=0;
  936.          textrec(t).bufend:=0;
  937.          textrec(t).bufptr:=@textrec(t).buffer;
  938.          textrec(t).name:=s;
  939.          textrec(t).openfunc:=@fileopenfunc;
  940.       end;
  941.  
  942.     procedure assign(var f : file;const name : string);
  943.  
  944.       begin
  945.          filerec(f).name:=name;
  946.          filerec(f).mode:=fmclosed;
  947.       end;
  948.  
  949.     procedure rewrite(var t : text);[iocheck];
  950.  
  951.       begin
  952.          textrec(t).mode:=fmoutput;
  953.          dateifunc(textrec(t).openfunc)(textrec(t));
  954.       end;
  955.  
  956.     procedure reset(var t : text);[iocheck];
  957.  
  958.       begin
  959.          textrec(t).mode:=fminput;
  960.          dateifunc(textrec(t).openfunc)(textrec(t));
  961.       end;
  962.  
  963.     procedure append(var t : text);[iocheck];
  964.  
  965.       begin
  966.          textrec(t).mode:=fmappend;
  967.          dateifunc(textrec(t).openfunc)(textrec(t));
  968.       end;
  969.  
  970.     procedure w(len : longint;var f : textrec;var s : string);[public,alias: 'WRITE_TEXT_STRING'];
  971.  
  972.       var
  973.          hbytes,pos,copybytes : longint;
  974.          hs : string;
  975.  
  976.       begin
  977.          if f.mode<>fmoutput then
  978.            exit;
  979.          copybytes:=length(s);
  980.          
  981.          if len>copybytes then
  982.            begin
  983.               hs:=space(len-copybytes);
  984.               w(0,f,hs);
  985.           end;        
  986.          pos:=1;
  987.          hbytes:=f.bufsize-f.bufpos;
  988.  
  989.          { wenn überhaupt kein Platz, dann ein flush durchführen }
  990.          if hbytes=0 then
  991.            dateifunc(f.flushfunc)(f);
  992.          
  993.          while copybytes>hbytes do
  994.            begin
  995.               move(s[pos],f.buffer[f.bufpos],hbytes);
  996.               f.bufpos:=f.bufpos+hbytes;
  997.               dec(copybytes,hbytes);
  998.               inc(pos,hbytes);
  999.               dateifunc(f.inoutfunc)(f);
  1000.               hbytes:=f.bufsize-f.bufpos;
  1001.            end;
  1002.          move(s[pos],f.buffer[f.bufpos],copybytes);
  1003.          f.bufpos:=f.bufpos+copybytes;  
  1004.       end;
  1005.  
  1006.     type
  1007.        array00 = array[0..0] of char;
  1008.  
  1009.     procedure w(len : longint;var f : textrec;const p : array00);[public,alias: 'WRITE_TEXT_PCHAR_AS_ARRAY'];
  1010.  
  1011.       var
  1012.          hbytes,pos,copybytes : longint;
  1013.          hs : string;
  1014.  
  1015.       begin
  1016.          if f.mode<>fmoutput then
  1017.            exit;
  1018.          copybytes:=strlen(p);
  1019.          if len>copybytes then
  1020.            begin
  1021.               hs:=space(len-copybytes);
  1022.               w(0,f,hs);
  1023.            end;
  1024.          pos:=0;
  1025.          hbytes:=f.bufsize-f.bufpos;
  1026.  
  1027.          { wenn überhaupt kein Platz, dann ein flush durchführen }
  1028.          if hbytes=0 then
  1029.            dateifunc(f.flushfunc)(f);
  1030.  
  1031.          while copybytes>hbytes do
  1032.            begin
  1033.               move(p[pos],f.buffer[f.bufpos],hbytes);
  1034.               f.bufpos:=f.bufpos+hbytes;
  1035.               dec(copybytes,hbytes);
  1036.               inc(pos,hbytes);
  1037.               dateifunc(f.inoutfunc)(f);
  1038.               hbytes:=f.bufsize-f.bufpos;
  1039.            end;
  1040.          move(p[pos],f.buffer[f.bufpos],copybytes);
  1041.          f.bufpos:=f.bufpos+copybytes;
  1042.       end;
  1043.  
  1044.     procedure wa(len : longint;var f : textrec;p : pchar);[public,alias: 'WRITE_TEXT_PCHAR_AS_POINTER'];
  1045.  
  1046.       begin
  1047.          w(len,f,p);
  1048.       end;
  1049.  
  1050.     procedure f1;[public,alias: 'FLUSH_STDOUT'];
  1051.  
  1052.       begin
  1053.          asm
  1054.             pushal
  1055.          end;
  1056.          dateifunc(textrec(output).flushfunc)(textrec(output));
  1057.          asm
  1058.             popal
  1059.          end;
  1060.       end;
  1061.  
  1062.     procedure flush(var t : text);[iocheck];
  1063.  
  1064.       begin
  1065.          if textrec(t).mode<>fmoutput then
  1066.            exit;
  1067.          dateifunc(textrec(t).flushfunc)(textrec(t));
  1068.       end;
  1069.  
  1070.     procedure doserase(p : pchar);forward;
  1071.     procedure dosrename(p1,p2 : pchar);forward;
  1072.  
  1073.     procedure erase(var t : text);[iocheck];
  1074.  
  1075.       var
  1076.          b : array[0..79] of char;
  1077.  
  1078.       begin
  1079.          if textrec(t).mode=fmclosed then
  1080.            begin
  1081.               move(textrec(t).name[1],b,length(textrec(t).name));
  1082.               b[length(textrec(t).name)]:=#0;
  1083.               doserase(b);
  1084.            end;
  1085.       end;
  1086.  
  1087.     procedure erase(var f : file);[iocheck];
  1088.  
  1089.       var
  1090.          b : array[0..79] of char;
  1091.  
  1092.       begin
  1093.          if filerec(f).mode=fmclosed then
  1094.            begin
  1095.               move(filerec(f).name[1],b,length(filerec(f).name));
  1096.               b[length(filerec(f).name)]:=#0;
  1097.               doserase(b);
  1098.            end;
  1099.       end;
  1100.  
  1101.     procedure rename(var f : file;const s : string);[iocheck];
  1102.  
  1103.       var
  1104.          b1,b2 : array[0..79] of char;
  1105.  
  1106.       begin
  1107.          if filerec(f).mode=fmclosed then
  1108.            begin
  1109.               move(filerec(f).name[1],b1,length(filerec(f).name));
  1110.               b1[length(filerec(f).name)]:=#0;
  1111.               move(s[1],b2,length(s));
  1112.               b2[length(s)]:=#0;
  1113.               dosrename(b1,b2);
  1114.               filerec(f).name:=s;
  1115.            end;
  1116.       end;
  1117.  
  1118.     procedure rename(var t : text;const s : string);[iocheck];
  1119.  
  1120.       var
  1121.          b1,b2 : array[0..79] of char;
  1122.  
  1123.       begin
  1124.          if textrec(t).mode=fmclosed then
  1125.            begin
  1126.               move(textrec(t).name[1],b1,length(textrec(t).name));
  1127.               b1[length(textrec(t).name)]:=#0;
  1128.               move(s[1],b2,length(s));
  1129.               b2[length(s)]:=#0;
  1130.               dosrename(b1,b2);
  1131.               textrec(t).name:=s;
  1132.            end;
  1133.       end;
  1134.  
  1135.     procedure w(len : longint;var t : textrec;l : longint);[public,alias: 'WRITE_TEXT_LONGINT'];
  1136.  
  1137.       var
  1138.          s : string;
  1139.  
  1140.       begin
  1141.          str(l,s);
  1142.          w(len,t,s);
  1143.       end;
  1144.       
  1145.     procedure w(fixkomma,len : longint;var t : textrec;r : real);[public,alias: 'WRITE_TEXT_REAL'];
  1146.  
  1147.       var
  1148.          s : string;
  1149.  
  1150.       begin
  1151.          str_real(fixkomma,r,s);
  1152.          w(len,t,s);
  1153.       end;
  1154.  
  1155.     { heißt wc, damit der Compiler keinen rekursiven Aufruf erzeugt }
  1156.  
  1157.     procedure wc(len : longint;var t : textrec;c : char);[public,alias: 'WRITE_TEXT_CHAR'];
  1158.     
  1159.       var
  1160.          hs : string;
  1161.  
  1162.       begin
  1163.          if t.mode<>fmoutput then
  1164.            exit;
  1165.            
  1166.          if len>1 then
  1167.            begin
  1168.               hs:=space(len-1);
  1169.               w(0,t,hs);
  1170.            end;
  1171.            
  1172.          if t.bufpos+1>=t.bufsize then
  1173.            dateifunc(t.flushfunc)(t);
  1174.          t.buffer[t.bufpos]:=c;
  1175.          inc(t.bufpos);
  1176.       end;
  1177.  
  1178.     procedure r(var f : textrec);[public,alias: 'READLN_TEXT'];
  1179.  
  1180.       begin
  1181.          { Datei muß zum Lesen geöffnet sein }
  1182.          if f.mode<>fminput then
  1183.            exit;
  1184.          { Noch Zeichen im Buffer? ansonsten laden }
  1185.          if f.bufpos>=f.bufend then
  1186.            dateifunc(f.inoutfunc)(f);
  1187.          while f.buffer[f.bufpos]<>#10 do
  1188.            begin
  1189.               { trotz Laden nichts im Buffer ? }
  1190.               if f.bufpos>=f.bufend then
  1191.                 { dann vergiss' s }
  1192.                 exit;
  1193.               inc(f.bufpos);
  1194.               if f.bufpos>=f.bufend then
  1195.                 dateifunc(f.inoutfunc)(f);
  1196.            end;
  1197.          inc(f.bufpos);
  1198.       end;
  1199.  
  1200.     procedure r(var f : textrec;var s : string);[public,alias: 'READ_TEXT_STRING'];
  1201.  
  1202.       begin
  1203.          { the file must be opened for input }
  1204.          if f.mode<>fminput then
  1205.            exit;
  1206.          { delete the string }
  1207.          s:='';
  1208.          { Noch Zeichen im Buffer? ansonsten Laden }
  1209.          if f.bufpos>=f.bufend then
  1210.            dateifunc(f.inoutfunc)(f);
  1211.  
  1212.          while f.buffer[f.bufpos]<>#10 do
  1213.            begin
  1214.               { if no chars in the buffer, then forget this }
  1215.               if f.bufpos>=f.bufend then
  1216.                 exit;
  1217.               if f.buffer[f.bufpos]<>#13 then
  1218.                 s:=s+f.buffer[f.bufpos];
  1219.               inc(f.bufpos);
  1220.               if f.bufpos>=f.bufend then
  1221.                 dateifunc(f.inoutfunc)(f);
  1222.            end;
  1223.       end;
  1224.  
  1225.     procedure r(var f : textrec;var l : longint);[public,alias: 'READ_TEXT_LONGINT'];
  1226.  
  1227.       var
  1228.          hs : string;
  1229.          code : word;
  1230.  
  1231.       label
  1232.          ready;
  1233.  
  1234.       begin
  1235.          if f.mode<>fminput then
  1236.            exit;
  1237.          { del the number }
  1238.          l:=0;
  1239.          { clear the string }
  1240.          hs:='';
  1241.          { Noch Zeichen im Buffer? ansonsten Laden }
  1242.          if f.bufpos>=f.bufend then
  1243.            dateifunc(f.inoutfunc)(f);
  1244.          { ignore spaces }
  1245.          while (f.buffer[f.bufpos]=#13) or
  1246.                (f.buffer[f.bufpos]=#10) or
  1247.                (f.buffer[f.bufpos]=#9) or
  1248.                (f.buffer[f.bufpos]=' ') do
  1249.            begin
  1250.               { if no chars in the buffer, then forget this }
  1251.               if f.bufpos>=f.bufend then
  1252.                 exit;
  1253.               inc(f.bufpos);
  1254.               if f.bufpos>=f.bufend then
  1255.                 dateifunc(f.inoutfunc)(f);
  1256.            end;
  1257.          { read the sign }
  1258.          if (f.buffer[f.bufpos]='-') or
  1259.             (f.buffer[f.bufpos]='+') then
  1260.            begin
  1261.               { if no chars in the buffer, then forget this }
  1262.               if f.bufpos>=f.bufend then
  1263.                 goto ready;
  1264.  
  1265.               hs:=hs+f.buffer[f.bufpos];
  1266.               inc(f.bufpos);
  1267.               if f.bufpos>=f.bufend then
  1268.                 dateifunc(f.inoutfunc)(f);
  1269.            end;
  1270.          while (ord(f.buffer[f.bufpos])>=ord('0')) and
  1271.            (ord(f.buffer[f.bufpos])<=ord('9')) do
  1272.            begin
  1273.               { if no chars in the buffer, then forget this }
  1274.               if f.bufpos>=f.bufend then
  1275.                 goto ready;
  1276.  
  1277.               hs:=hs+f.buffer[f.bufpos];
  1278.               inc(f.bufpos);
  1279.               if f.bufpos>=f.bufend then
  1280.                 dateifunc(f.inoutfunc)(f);
  1281.            end;
  1282.       ready:
  1283.          val(hs,l,code);
  1284.          if code<>0 then
  1285.            runerror(106);
  1286.       end;
  1287.  
  1288.     procedure r(var f : textrec;var c : char);[public,alias: 'READ_TEXT_CHAR'];
  1289.  
  1290.       var
  1291.          hs : string;
  1292.          code : word;
  1293.  
  1294.       begin
  1295.          c:=#0;
  1296.  
  1297.          { the file must be opened for input }
  1298.          if f.mode<>fminput then
  1299.            exit;
  1300.  
  1301.          { maybe reload }
  1302.          if f.bufpos>=f.bufend then
  1303.            dateifunc(f.inoutfunc)(f);
  1304.  
  1305.          if f.bufpos>=f.bufend then
  1306.            c:=#26
  1307.          else c:=f.buffer[f.bufpos];
  1308.  
  1309.          inc(f.bufpos);
  1310.       end;
  1311.  
  1312.     procedure r(var f : textrec;var d : double);[public,alias: 'READ_TEXT_REAL'];
  1313.  
  1314.       var
  1315.          hs : string;
  1316.          code : word;
  1317.  
  1318.       label
  1319.          ready;
  1320.  
  1321.       begin
  1322.          { f... long code }
  1323.          if f.mode<>fminput then
  1324.            exit;
  1325.          { del the number }
  1326.          d:=0.0;
  1327.          { clear the string }
  1328.          hs:='';
  1329.  
  1330.          { maybe reload }
  1331.          if f.bufpos>=f.bufend then
  1332.            dateifunc(f.inoutfunc)(f);
  1333.  
  1334.          { ignore spaces }
  1335.          while (f.buffer[f.bufpos]=#13) or
  1336.                (f.buffer[f.bufpos]=#10) or
  1337.                (f.buffer[f.bufpos]=#9) or
  1338.                (f.buffer[f.bufpos]=' ') do
  1339.            begin
  1340.               { if no chars in the buffer, then forget this }
  1341.               if f.bufpos>=f.bufend then
  1342.                 exit;
  1343.               inc(f.bufpos);
  1344.               if f.bufpos>=f.bufend then
  1345.                 dateifunc(f.inoutfunc)(f);
  1346.            end;
  1347.  
  1348.          { read the sign }
  1349.          if (f.buffer[f.bufpos]='-') or
  1350.             (f.buffer[f.bufpos]='+') then
  1351.            begin
  1352.               { if no chars in the buffer, then forget this }
  1353.               if f.bufpos>=f.bufend then
  1354.                 goto ready;
  1355.  
  1356.               hs:=hs+f.buffer[f.bufpos];
  1357.               inc(f.bufpos);
  1358.               if f.bufpos>=f.bufend then
  1359.                 dateifunc(f.inoutfunc)(f);
  1360.            end;
  1361.          while (ord(f.buffer[f.bufpos])>=ord('0')) and
  1362.            (ord(f.buffer[f.bufpos])<=ord('9')) do
  1363.            begin
  1364.               { if no chars in the buffer, then forget this }
  1365.               if f.bufpos>=f.bufend then
  1366.                 goto ready;
  1367.  
  1368.               hs:=hs+f.buffer[f.bufpos];
  1369.               inc(f.bufpos);
  1370.               if f.bufpos>=f.bufend then
  1371.                 dateifunc(f.inoutfunc)(f);
  1372.            end;
  1373.          { comma ? }
  1374.          if (f.buffer[f.bufpos]='.') then
  1375.            begin
  1376.               { if no chars in the buffer, then forget this }
  1377.               if f.bufpos>=f.bufend then
  1378.                 goto ready;
  1379.  
  1380.               hs:=hs+'.';
  1381.               inc(f.bufpos);
  1382.               if f.bufpos>=f.bufend then
  1383.                 dateifunc(f.inoutfunc)(f);
  1384.  
  1385.               while (ord(f.buffer[f.bufpos])>=ord('0')) and
  1386.                 (ord(f.buffer[f.bufpos])<=ord('9')) do
  1387.                 begin
  1388.                    { if no chars in the buffer, then forget this }
  1389.                    if f.bufpos>=f.bufend then
  1390.                      goto ready;
  1391.  
  1392.                    hs:=hs+f.buffer[f.bufpos];
  1393.                    inc(f.bufpos);
  1394.                    if f.bufpos>=f.bufend then
  1395.                      dateifunc(f.inoutfunc)(f);
  1396.                 end;
  1397.            end;
  1398.  
  1399.          { exponent ? }
  1400.          if (upcase(f.buffer[f.bufpos])='E') then
  1401.            begin
  1402.               { if no chars in the buffer, then forget this }
  1403.               if f.bufpos>=f.bufend then
  1404.                 goto ready;
  1405.  
  1406.               hs:=hs+'E';
  1407.               inc(f.bufpos);
  1408.               if f.bufpos>=f.bufend then
  1409.                 dateifunc(f.inoutfunc)(f);
  1410.  
  1411.               { read the sign of the exponent }
  1412.               if (f.buffer[f.bufpos]='-') or
  1413.                  (f.buffer[f.bufpos]='+') then
  1414.                 begin
  1415.                    { if no chars in the buffer, then forget this }
  1416.                    if f.bufpos>=f.bufend then
  1417.                      goto ready;
  1418.  
  1419.                    hs:=hs+f.buffer[f.bufpos];
  1420.                    inc(f.bufpos);
  1421.                    if f.bufpos>=f.bufend then
  1422.                      dateifunc(f.inoutfunc)(f);
  1423.                 end;
  1424.               while (ord(f.buffer[f.bufpos])>=ord('0')) and
  1425.                 (ord(f.buffer[f.bufpos])<=ord('9')) do
  1426.                 begin
  1427.                    { if no chars in the buffer, then forget this }
  1428.                    if f.bufpos>=f.bufend then
  1429.                      goto ready;
  1430.  
  1431.                    hs:=hs+f.buffer[f.bufpos];
  1432.                    inc(f.bufpos);
  1433.                    if f.bufpos>=f.bufend then
  1434.                      dateifunc(f.inoutfunc)(f);
  1435.                 end;
  1436.            end;
  1437.       ready:
  1438.          val(hs,d,code);
  1439.          if code<>0 then
  1440.            runerror(106);
  1441.       end;
  1442.  
  1443.     function ioresult : word;
  1444.  
  1445.       begin
  1446.          ioresult:=inoutres;
  1447.          inoutres:=0;
  1448.       end;
  1449.  
  1450.     procedure blockread(var f : file;var buf;count : word;var result : word);[iocheck];
  1451.  
  1452.       var
  1453.          rl : longint;
  1454.  
  1455.       begin
  1456.          blockread(f,buf,count,rl);
  1457.          result:=rl;
  1458.       end;
  1459.  
  1460.     procedure w(var t : textrec);[public,alias: 'WRITELN_TEXT'];
  1461.  
  1462.       var
  1463.          hs : string;
  1464.  
  1465.       begin
  1466.          hs:=#13#10;
  1467.          w(0,t,hs);
  1468.       end;
  1469.  
  1470.     procedure close(var t : text);[public,alias: 'CLOSE_TEXT',iocheck];
  1471.  
  1472.       begin
  1473.          if (textrec(t).mode<>fmclosed) then
  1474.            begin
  1475.               dateifunc(textrec(t).flushfunc)(textrec(t));
  1476.               textrec(t).mode:=fmclosed;
  1477.               dateifunc(textrec(t).closefunc)(textrec(t));
  1478.            end;
  1479.       end;
  1480.  
  1481.     procedure initexception;[public,alias: 'INITEXCEPTION'];
  1482.  
  1483.       begin
  1484.          writeln('Exception während der Programminitialisierung aufgetreten');
  1485.          halt;
  1486.       end;
  1487.  
  1488.     function ptr(sel,off : word) : pointer;
  1489.  
  1490.       begin
  1491. {$ifdef DOS}
  1492.          ptr:=pointer($e0000000+sel shl 4+off);
  1493. {$else}
  1494.          ptr:=pointer(sel shl 4+off);
  1495. {$endif}
  1496.       end;
  1497.  
  1498.     function eof : boolean;
  1499.  
  1500.       begin
  1501.          eof:=eof(input);
  1502.       end;
  1503.  
  1504.     function eoln(var t : text) : boolean;
  1505.  
  1506.       begin
  1507.          { maybe we need new data }
  1508.          if textrec(t).bufpos>=textrec(t).bufend then
  1509.            dateifunc(textrec(t).inoutfunc)(textrec(t));
  1510.  
  1511.          eoln:=eof or
  1512.            (textrec(t).buffer[textrec(t).bufpos]=#13) or
  1513.            (textrec(t).buffer[textrec(t).bufpos]=#10);
  1514.       end;
  1515.  
  1516.     function eoln : boolean;
  1517.  
  1518.       begin
  1519.          eoln:=eoln(input);
  1520.       end;
  1521.  
  1522. {****************************************************************************
  1523.                     subroutines for string handling
  1524.  ****************************************************************************}
  1525.  
  1526.     function copy(const s : string;index : integer;count : byte): string;
  1527.  
  1528.        var
  1529.           i : longint;
  1530.  
  1531.        begin
  1532.           if count < 0 then count := 0;
  1533.           if index <= 0 then index := 1;
  1534.           if index <= ord(s[0]) then
  1535.             begin
  1536.                if count + index > ord(s[0]) then copy[0] := chr (ord(s[0]) - index +1)
  1537.                  else copy[0] := chr (count);
  1538.                for i := 1 to ord (s[0]) do copy[i] := s [index -1 + i];
  1539.             end
  1540.           else copy[0] := #0;
  1541.        end;
  1542.  
  1543.     procedure delete(var s : string;index : integer;count : integer);
  1544.  
  1545.        var i : longint;
  1546.  
  1547.        begin
  1548.           if index <= 0 then
  1549.             begin
  1550.                count := count + index -1;
  1551.                index := 1;
  1552.             end;
  1553.           if count <= 0 then exit;
  1554.           if ord (s[0]) >= index then
  1555.             begin
  1556.                if count + index > ord (s[0]) then count:= ord (s[0]) -index + 1;
  1557.                  for i := 0 to ord (s[0]) - (count+index) do
  1558.                    s [i+index] := s[i+count+index];
  1559.                s[0] := chr(ord (s[0]) - count);
  1560.             end;
  1561.        end;
  1562.  
  1563.     procedure insert(const source : string;var s : string;index : integer);
  1564.  
  1565.        var s3 : string;
  1566.  
  1567.        begin
  1568.           if index <= 0 then index := 1;
  1569.           s3 := copy (s, index, length(s));
  1570.           if index > length (s) then index := ord(s[0]) +1;
  1571.           s[0] := chr (index - 1);
  1572.           s := s + source + s3;
  1573.        end;
  1574.  
  1575.     function pos(const substr : string;const s : string): byte;
  1576.  
  1577.        var i : longint;
  1578.            j : byte;
  1579.            e : boolean;
  1580.  
  1581.        begin
  1582.           i := 0;
  1583.           j := 0;
  1584.           e := true;
  1585.           if substr = '' then e := false;
  1586.           while (e) and (i <= length (s) - length (substr)) do
  1587.             begin
  1588.                inc (i);
  1589.                if substr = copy (s,i,length (substr)) then
  1590.                  begin
  1591.                     j := i;
  1592.                     e := false;
  1593.                  end;
  1594.             end;
  1595.           pos := j;
  1596.        end;
  1597.  
  1598.     function upcase(c : char) : char;
  1599.  
  1600.        begin
  1601.           if (c >= #97) and (c <= #122) then c := chr(ord (c) - 32)
  1602.           else if (c >= #128) and (c <= #165) then
  1603.             case c of
  1604.                  #129 : c := #154;  {D}
  1605.                  #132 : c := #142;  {D}
  1606.                  #148 : c := #153;  {D}
  1607.                  #130 : c := #144;  {F}
  1608.                  #135 : c := #128;  {F}
  1609.                  #134 : c := #143;  {E}
  1610.                  #164 : c := #165;  {E}
  1611.             end;
  1612.           upcase := c;
  1613.        end;
  1614.  
  1615.     function upcase(const s : string) : string;
  1616.  
  1617.        var i : longint;
  1618.  
  1619.        begin
  1620.           upcase[0]:=s[0];
  1621.           for i := 1 to length (s) do 
  1622.             upcase[i] := upcase (s[i]);
  1623.        end;
  1624.  
  1625.     function lowercase(c : char) : char;
  1626.  
  1627.        begin
  1628.           if (c >= #65) and (c <= #90) then c := chr(ord (c) + 32)
  1629.           else if (c >= #128) and (c <= #165) then
  1630.             case c of
  1631.                  #154 : c := #129;  {D}
  1632.                  #142 : c := #132;  {D}
  1633.                  #153 : c := #148;  {D}
  1634.                  #144 : c := #130;  {F}
  1635.                  #128 : c := #135;  {F}
  1636.                  #143 : c := #134;  {E}
  1637.                  #165 : c := #164;  {E}
  1638.             end;
  1639.           lowercase := c;
  1640.        end;
  1641.  
  1642.     function lowercase(const s : string) : string;
  1643.  
  1644.       var i : longint;
  1645.  
  1646.       begin
  1647.          lowercase [0] := s[0];
  1648.          for i := 1 to length (s) do 
  1649.            lowercase[i] := lowercase (s[i]);
  1650.       end;
  1651.  
  1652.     function space (b : byte): string;
  1653.  
  1654.        var i : longint;
  1655.  
  1656.        begin
  1657.           space[0] := chr(b);
  1658.           for i := 1 to b do space[i] := #32;
  1659.        end;
  1660.  
  1661. { old version doesn't like this }
  1662. {$ifndef VER0_6_5}
  1663. {$ifndef VER0_6_4}
  1664.     constructor tobject.create;
  1665.  
  1666.       begin
  1667.       end;
  1668.  
  1669.     destructor tobject.free;
  1670.  
  1671.       begin
  1672.       end;
  1673.  
  1674. {$endif}
  1675. {$endif}
  1676.